package org.example.util;

import org.objectweb.asm.*;

import java.io.IOException;

import static org.objectweb.asm.Opcodes.*;

/**
 * @ClassName: AsmUtils
 * @Description:
 * @Author: YourName
 * @Date: 2025/2/10
 */

public class AsmUtils {
    public static void testModifyCalss(String classname) throws IOException {
        ClassReader cr = new ClassReader(classname);
        final ClassWriter cw=new ClassWriter(cr,0);
//        cr.accept(cw, 0);//可以直接接受一个writer,实现复制
        cr.accept(new ClassVisitor(ASM4,cw) {//接受一个带classWriter的visitor，实现定制化方法拷贝或者属性删除字段
            @Override
            public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                System.out.println("visit method:"+name+"====> "+descriptor);

                if("testA".equals(name)){//拷贝的过程中删除一个方法
                    return null;
                }

                if("testC".equals(name)){//将testC public方法变成protect
                    access=ACC_PROTECTED;
                }
                return super.visitMethod(access, name, descriptor, signature, exceptions);
            }

            @Override
            public void visitEnd() {
                //特别注意的是：要为类增加属性和方法，放到visitEnd中，避免破坏之前已经排列好的类结构，在结尾添加新结构
                //增加一个字段（注意不能重复）,注意最后都要visitEnd
                FieldVisitor fv = cv.visitField(ACC_PUBLIC, "phone", "Ljava/lang/String;", null, null);
                fv.visitEnd();//不能缺少visitEnd

                //增加一个方法
                MethodVisitor mv=cv.visitMethod(ACC_PUBLIC,"getPhone","()Ljava/lang/String;",null,null);
                mv.visitCode();
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD,classname,"phone","Ljava/lang/String;");
                mv.visitInsn(IRETURN);
                mv.visitMaxs(1, 1);
                mv.visitEnd();//不能缺少visitEnd
                super.visitEnd();//注意原本的visiEnd不能少
            }
        },0);
    }
}
